package com.domainchen.framework.core.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.DiskFileUpload;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.domainchen.framework.common.config.Global;
import com.domainchen.framework.common.util.CollectionUtil;
import com.domainchen.framework.common.util.FileUtil;
import com.domainchen.framework.common.util.StreamUtil;
import com.domainchen.framework.common.util.StringUtils;
import com.domainchen.framework.core.bean.FileParam;
import com.domainchen.framework.core.bean.FormParam;
import com.domainchen.framework.core.bean.Param;

/**
 * @author domainchen or cytxiamen@163.com
 * @version 创建时间：2016年3月15日 下午6:42:53
 * @类说明 文件上传对象
 */
public final class UploadHolder {

	private static final Logger logger = LoggerFactory.getLogger(UploadHolder.class);

	/**
	 * apache commmons-fileupload 提供的Servlet 文件上传对象
	 */
	private static ServletFileUpload servletFileUpload;

	public static void init(ServletContext servletContext) {
		File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
		servletFileUpload = new ServletFileUpload(
				new DiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD, repository));
		int uploadLimit = Global.getAppUploadLimit();
		if (uploadLimit == 0) {
			servletFileUpload.setFileSizeMax(uploadLimit * 1024 * 1024);
		}
	}

	/**
	 * 判断是否为 Multipart 类型
	 * 
	 * @param request
	 * @return
	 */
	public static boolean isMultipart(HttpServletRequest request) {
		return ServletFileUpload.isMultipartContent(request);
	}

	public static Param createParam(HttpServletRequest request) throws IOException {
		List<FormParam> formParamList = new ArrayList<FormParam>();
		List<FileParam> fileParamList = new ArrayList<FileParam>();
		try {
			Map<String, List<FileItem>> fileItemListMap = servletFileUpload.parseParameterMap(request);
			if (CollectionUtil.isNotEmpty(fileItemListMap)) {
				for (Map.Entry<String, List<FileItem>> fileItemListEntity : fileItemListMap.entrySet()) {
					String fieldName = fileItemListEntity.getKey();
					List<FileItem> fileItemList = fileItemListEntity.getValue();
					if (CollectionUtil.isNotEmpty(fileItemList)) {
						for (FileItem fileItem : fileItemList) {
							if (fileItem.isFormField()) {
								String fieldValue = fileItem.getString("UTF-8");
								formParamList.add(new FormParam(fieldName, fieldValue));
							} else {
								String fileName = FileUtil
										.getRealFileName(new String(fileItem.getName().getBytes(), "UTF-8"));
								if (StringUtils.isNotEmpty(fileName)) {
									long fileSize = fileItem.getSize();
									String contextType = fileItem.getContentType();
									InputStream inputStream = fileItem.getInputStream();
									fileParamList.add(
											new FileParam(fieldName, fileName, fileSize, contextType, inputStream));

								}

							}
						}
					}
				}
			}
		} catch (Exception e) {
			logger.error("create param failure ", e);
			throw new RuntimeException(e);

		}
		return new Param(formParamList, fileParamList);
	}

	/**
	 * 
	 * @pa上传文件 ram basePath
	 * @param fileParam
	 */
	public static void uploadFile(String basePath, FileParam fileParam) {
		try {
			if (null != fileParam) {
				String filePath = basePath + fileParam.getFileName();
				FileUtil.createFile(filePath);
				InputStream inputStream = new BufferedInputStream(fileParam.getInputStream());
				OutputStream outPutStream = new BufferedOutputStream(new FileOutputStream(filePath));
				StreamUtil.copyStream(inputStream, outPutStream);
			}
		} catch (Exception e) {
			logger.error("upload file failure ", e);
			throw new RuntimeException(e);
		}
	}

	/**
	 * 批量上传文件
	 * 
	 * @param basePath
	 * @param fileParamList
	 */
	public static void uploadFile(String basePath, List<FileParam> fileParamList) {
		try {
			if (CollectionUtil.isNotEmpty(fileParamList)) {
				for (FileParam fileParam : fileParamList) {
					uploadFile(basePath, fileParam);
				}
			}
		} catch (Exception e) {
			logger.error("upload file failure ", e);
			throw new RuntimeException(e);
		}
	}
}
